package org.japo.java.matisse.samples;

import java.awt.Color;
import java.awt.Font;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import javax.swing.JOptionPane;
import org.japo.java.entities.Rotulo;

public class SeleccionEstiloAsistido extends javax.swing.JFrame {

    // Separador de items
    private final String SEPARADOR = ",";

    // Modelo
    private Rotulo modelo;

    // Archivo de persistencia - Carpeta del proyecto
    private final String ARCHIVO = "rotulo.txt";

    public SeleccionEstiloAsistido() {
        iniciarAnterior();
        initComponents();
        iniciarPosterior();
    }

    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        pnlEstilo = new javax.swing.JPanel();
        cbxNegrita = new javax.swing.JCheckBox();
        cbxCursiva = new javax.swing.JCheckBox();
        pnlArchivo = new javax.swing.JPanel();
        btnCargar = new javax.swing.JButton();
        btnGuardar = new javax.swing.JButton();
        lblMuestra = new javax.swing.JLabel();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setTitle("Estilo asistido");
        setResizable(false);

        pnlEstilo.setBorder(javax.swing.BorderFactory.createTitledBorder("Estilo"));

        cbxNegrita.setText("Negrita");
        cbxNegrita.setMaximumSize(new java.awt.Dimension(80, 24));
        cbxNegrita.setMinimumSize(new java.awt.Dimension(80, 24));
        cbxNegrita.setPreferredSize(new java.awt.Dimension(80, 24));
        cbxNegrita.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                cbxNegritaActionPerformed(evt);
            }
        });

        cbxCursiva.setText("Cursiva");
        cbxCursiva.setMaximumSize(new java.awt.Dimension(83, 29));
        cbxCursiva.setMinimumSize(new java.awt.Dimension(83, 29));
        cbxCursiva.setPreferredSize(new java.awt.Dimension(83, 29));
        cbxCursiva.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                cbxCursivaActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout pnlEstiloLayout = new javax.swing.GroupLayout(pnlEstilo);
        pnlEstilo.setLayout(pnlEstiloLayout);
        pnlEstiloLayout.setHorizontalGroup(
            pnlEstiloLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(pnlEstiloLayout.createSequentialGroup()
                .addContainerGap()
                .addComponent(cbxNegrita, javax.swing.GroupLayout.PREFERRED_SIZE, 80, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, pnlEstiloLayout.createSequentialGroup()
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addComponent(cbxCursiva, javax.swing.GroupLayout.PREFERRED_SIZE, 80, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap())
        );
        pnlEstiloLayout.setVerticalGroup(
            pnlEstiloLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(pnlEstiloLayout.createSequentialGroup()
                .addComponent(cbxNegrita, javax.swing.GroupLayout.PREFERRED_SIZE, 24, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(18, 18, 18)
                .addComponent(cbxCursiva, javax.swing.GroupLayout.PREFERRED_SIZE, 24, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap(11, Short.MAX_VALUE))
        );

        pnlArchivo.setBorder(javax.swing.BorderFactory.createTitledBorder("Archivo"));

        btnCargar.setText("Cargar");
        btnCargar.setMaximumSize(new java.awt.Dimension(80, 24));
        btnCargar.setMinimumSize(new java.awt.Dimension(80, 24));
        btnCargar.setPreferredSize(new java.awt.Dimension(80, 24));
        btnCargar.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnCargarActionPerformed(evt);
            }
        });

        btnGuardar.setText("Guardar");
        btnGuardar.setMaximumSize(new java.awt.Dimension(80, 24));
        btnGuardar.setMinimumSize(new java.awt.Dimension(80, 24));
        btnGuardar.setPreferredSize(new java.awt.Dimension(80, 24));
        btnGuardar.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnGuardarActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout pnlArchivoLayout = new javax.swing.GroupLayout(pnlArchivo);
        pnlArchivo.setLayout(pnlArchivoLayout);
        pnlArchivoLayout.setHorizontalGroup(
            pnlArchivoLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(pnlArchivoLayout.createSequentialGroup()
                .addContainerGap()
                .addComponent(btnCargar, javax.swing.GroupLayout.PREFERRED_SIZE, 80, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, pnlArchivoLayout.createSequentialGroup()
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addComponent(btnGuardar, javax.swing.GroupLayout.PREFERRED_SIZE, 80, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap())
        );

        pnlArchivoLayout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {btnCargar, btnGuardar});

        pnlArchivoLayout.setVerticalGroup(
            pnlArchivoLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(pnlArchivoLayout.createSequentialGroup()
                .addComponent(btnCargar, javax.swing.GroupLayout.PREFERRED_SIZE, 24, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(18, 18, 18)
                .addComponent(btnGuardar, javax.swing.GroupLayout.PREFERRED_SIZE, 24, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );

        lblMuestra.setBackground(new java.awt.Color(255, 255, 255));
        lblMuestra.setFont(new java.awt.Font("Tahoma", 0, 18)); // NOI18N
        lblMuestra.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        lblMuestra.setText("Texto de prueba");
        lblMuestra.setBorder(javax.swing.BorderFactory.createBevelBorder(javax.swing.border.BevelBorder.LOWERED));
        lblMuestra.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        lblMuestra.setOpaque(true);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
                    .addComponent(lblMuestra, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(pnlEstilo, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(pnlArchivo, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(lblMuestra, javax.swing.GroupLayout.PREFERRED_SIZE, 104, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(pnlEstilo, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(pnlArchivo, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );

        pack();
        setLocationRelativeTo(null);
    }// </editor-fold>//GEN-END:initComponents

    private void btnGuardarActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnGuardarActionPerformed
        procesarGuarda();
    }//GEN-LAST:event_btnGuardarActionPerformed

    private void btnCargarActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnCargarActionPerformed
        procesarCarga();
    }//GEN-LAST:event_btnCargarActionPerformed

    private void cbxNegritaActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cbxNegritaActionPerformed
        procesarCambioEstilo();
    }//GEN-LAST:event_cbxNegritaActionPerformed

    private void cbxCursivaActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cbxCursivaActionPerformed
        procesarCambioEstilo();
    }//GEN-LAST:event_cbxCursivaActionPerformed

    public static void main(String args[]) {
        //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
        /*
         * If Nimbus (introduced in Java SE 6) is not available, stay with the
         * default look and feel. For details see
         * http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html
         */
        try {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if ("Windows".equals(info.getName())) {
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (ClassNotFoundException ex) {
            java.util.logging.Logger.getLogger(SeleccionEstiloAsistido.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (InstantiationException ex) {
            java.util.logging.Logger.getLogger(SeleccionEstiloAsistido.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            java.util.logging.Logger.getLogger(SeleccionEstiloAsistido.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (javax.swing.UnsupportedLookAndFeelException ex) {
            java.util.logging.Logger.getLogger(SeleccionEstiloAsistido.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
        //</editor-fold>

        java.awt.EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                new SeleccionEstiloAsistido().setVisible(true);
            }
        });
    }
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton btnCargar;
    private javax.swing.JButton btnGuardar;
    private javax.swing.JCheckBox cbxCursiva;
    private javax.swing.JCheckBox cbxNegrita;
    private javax.swing.JLabel lblMuestra;
    private javax.swing.JPanel pnlArchivo;
    private javax.swing.JPanel pnlEstilo;
    // End of variables declaration//GEN-END:variables

    private void iniciarPosterior() {
        generarModelo();
        actualizarControles();
    }

    private void exportarModelo() throws Exception {
        // Lectura de un fichero de texto
        try (PrintWriter pw = new PrintWriter(new FileWriter(ARCHIVO))) {
            // Exportar modelo > items
            String[] items = exportarItems(modelo);

            // Guardar items
            guardarItems(pw, items, SEPARADOR);
        }
    }

    private String[] exportarItems(Rotulo modelo) {
        // Crea una lista vacía
        String[] items = new String[Rotulo.NUMERO_ITEMS];

        // Texto
        exportarTexto(modelo, items);

        // Fuente
        exportarFuente(modelo, items);

        // Color de frente
        exportarFrente(modelo, items);

        // Color de fondo
        exportarFondo(modelo, items);

        // Devuelve la lista
        return items;
    }

    private void exportarTexto(Rotulo modelo, String[] items) {
        items[Rotulo.TEXTO] = modelo.getTexto();
    }

    private void exportarFuente(Rotulo modelo, String[] items) {
        // Tipografia
        items[Rotulo.TIPOGRAFIA] = modelo.getFuente().getFamily();

        // Estilo
        items[Rotulo.ESTILO] = modelo.getFuente().getStyle() + "";

        // Talla
        items[Rotulo.TALLA] = modelo.getFuente().getSize() + "";
    }

    private void exportarFrente(Rotulo modelo, String[] items) {
        // Frente - Rojo
        items[Rotulo.FRENTE_R] = modelo.getColorFrente().getRed() + "";

        // Frente - Verde
        items[Rotulo.FRENTE_V] = modelo.getColorFrente().getGreen() + "";

        // Frente - Azul
        items[Rotulo.FRENTE_A] = modelo.getColorFrente().getBlue() + "";
    }

    private void exportarFondo(Rotulo modelo, String[] items) {
        // Frente - Rojo
        items[Rotulo.FONDO_R] = modelo.getColorFondo().getRed() + "";

        // Frente - Verde
        items[Rotulo.FONDO_V] = modelo.getColorFondo().getGreen() + "";

        // Frente - Azul
        items[Rotulo.FONDO_A] = modelo.getColorFondo().getBlue() + "";
    }

    private void guardarItems(PrintWriter pw, String[] items, String SEPARADOR) {
        // Escribe el primer item por separado
        pw.print(items[0]);

        // Escribe el resto de los items
        for (int i = 1; i < items.length; i++) {
            pw.print(SEPARADOR + items[i]);
        }
    }

    private void importarModelo() throws Exception {
        // Lectura de un fichero de texto
        try (BufferedReader br =
                new BufferedReader(new FileReader(ARCHIVO))) {
            // Generar items
            String[] items = obtenerItems(br, SEPARADOR);

            // Importar items
            importarItems(modelo, items);
        }
    }

    private void actualizarAspecto() {
        // Texto de la muestra
        lblMuestra.setText(modelo.getTexto());

        // Fuente de la muestra
        lblMuestra.setFont(modelo.getFuente());

        // Color de frente
        lblMuestra.setForeground(modelo.getColorFrente());

        // Color de fondo
        lblMuestra.setBackground(modelo.getColorFondo());
    }

    private void actualizarControles() {
        // Obtiene el estilo de la entidad
        int estilo = modelo.getFuente().getStyle();

        // Establece los controles
        if (estilo == Font.PLAIN) {
            cbxNegrita.setSelected(false);
            cbxCursiva.setSelected(false);
        } else if (estilo == Font.BOLD) {
            cbxNegrita.setSelected(true);
            cbxCursiva.setSelected(false);
        } else if (estilo == Font.ITALIC) {
            cbxNegrita.setSelected(false);
            cbxCursiva.setSelected(true);
        } else {
            cbxNegrita.setSelected(true);
            cbxCursiva.setSelected(true);
        }
    }

    private void actualizarModelo() {
        // Obtiene la fuente del modelo
        Font f = modelo.getFuente();

        // Obtener la tipografia
        String tipografia = f.getFamily();

        // Negrita
        int negrita = cbxNegrita.isSelected() ? Font.BOLD : Font.PLAIN;

        // Negrita
        int cursiva = cbxCursiva.isSelected() ? Font.ITALIC : Font.PLAIN;

        // Estilo de la fuente
        int estilo = negrita + cursiva;

        // Talla de la fuente
        int talla = f.getSize();

        // Genera la nueva fuente para el modelo
        f = new Font(tipografia, estilo, talla);

        // Actualizar el modelo
        modelo.setFuente(f);
    }

    private void iniciarAnterior() {
    }

    private void procesarCarga() {
        try {
            // Soporte > modelo
            importarModelo();
            
            // Modelo > aspecto
            actualizarAspecto();
            
            // Modelo > controles
            actualizarControles();
        } catch (Exception e) {
            String msg = "Error al cargar la configuración";
            JOptionPane.showMessageDialog(this, msg);
        }
    }

    private void importarTexto(Rotulo modelo, String[] listaTokens) {
        modelo.setTexto(listaTokens[Rotulo.TEXTO]);
    }

    private void importarFuente(Rotulo modelo, String[] listaTokens)
            throws NumberFormatException {
        // Tipografia de la fuente
        String tipografia = listaTokens[Rotulo.TIPOGRAFIA];

        // Estilo de la fuente
        int estilo = Integer.parseInt(listaTokens[Rotulo.ESTILO]);

        // Talla de la fuente
        int talla = Integer.parseInt(listaTokens[Rotulo.TALLA]);

        // Fuente
        Font f = new Font(tipografia, estilo, talla);

        // Importar fuente
        modelo.setFuente(f);
    }

    private void importarFrente(Rotulo modelo, String[] listaTokens)
            throws NumberFormatException {
        // Componentes de color
        int r = Integer.parseInt(listaTokens[Rotulo.FRENTE_R]);
        int v = Integer.parseInt(listaTokens[Rotulo.FRENTE_V]);
        int a = Integer.parseInt(listaTokens[Rotulo.FRENTE_A]);

        // Instancia el color
        Color c = new Color(r, v, a);

        // Importar color
        modelo.setColorFrente(c);
    }

    private void importarFondo(Rotulo modelo, String[] listaTokens)
            throws NumberFormatException {
        // Componentes de color
        int r = Integer.parseInt(listaTokens[Rotulo.FONDO_R]);
        int v = Integer.parseInt(listaTokens[Rotulo.FONDO_V]);
        int a = Integer.parseInt(listaTokens[Rotulo.FONDO_A]);

        // Instancia el color
        Color c = new Color(r, v, a);

        // Importar color
        modelo.setColorFondo(c);
    }

    private void importarItems(Rotulo modelo, String[] items)
            throws NumberFormatException {
        // Texto
        importarTexto(modelo, items);

        // Fuente
        importarFuente(modelo, items);

        // Color de frente
        importarFrente(modelo, items);

        // Color de fondo
        importarFondo(modelo, items);
    }

    private String[] obtenerItems(BufferedReader br, String SEPARADOR)
            throws IOException {
        // Linea de texto a leer
        String linea = br.readLine();

        // Genera la lista de items
        return linea.split(SEPARADOR);
    }

    private void generarModelo() {
        // Extrae parámetros tiempo de diseño
        String texto = lblMuestra.getText();
        Font fuente = lblMuestra.getFont();
        Color colorFrente = lblMuestra.getForeground();
        Color colorFondo = lblMuestra.getBackground();

        // Instancia el modelo con los valores de diseño
        modelo = new Rotulo(texto, fuente, colorFrente, colorFondo);
    }

    private void procesarGuarda() {
        try {
            // Modelo > soporte
            exportarModelo();
        } catch (Exception e) {
            String msg = "Error al guardar la configuración";
            JOptionPane.showMessageDialog(this, msg);
        }
    }

    private void procesarCambioEstilo() {
        // Controles > modelo
        actualizarModelo();

        // Modelo > aspecto
        actualizarAspecto();
    }
}
